﻿//-----------------------------------------------------------------------------------------------------------
// Wbfs Engine (WBFSe) Project by Omega Frost 
// http://wbfse.codeplex.com/
//
// WBFSe is Licensed under the terms of the 
// Microsoft Reciprocal License (Ms-RL)
//-----------------------------------------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using WBFSe.Attributes;
using System.IO;
using WBFSe.OS;

namespace WBFSe.IO.Drives
{
    /// <summary>
    /// A device recognized by the Operating System
    /// </summary>
    class OSDrive : IWbfsDriveInfo
    {
        // Variables

        private System.IO.DriveInfo info;
        private bool fatWbfs;
        private bool isSparse;

        // Properties

        /// <summary>
        /// The drive name in format X:\
        /// </summary>
        public String Name
        {
            get { return info.Name; }
        }

        /// <summary>
        /// The drive label
        /// </summary>
        public String Label
        {
            get { return this.info.VolumeLabel; }
            set { this.info.VolumeLabel = value; }
        }

        /// <summary>
        /// The drive FS
        /// </summary>
        public String FileSystem
        {
            get { return this.info.DriveFormat; }
        }

        /// <summary>
        /// The drive type
        /// </summary>
        public DriveType Type
        {
            get { return info.DriveType; }
        }

        /// <summary>
        /// The partition is WBFS
        /// </summary>
        public bool IsWbfs
        {
            get { return false; }
        }

        /// <summary>
        /// The drive is marked as a WbfsFat
        /// </summary>
        public bool IsWbfsFat
        {
            get { return this.fatWbfs; }
            set { this.fatWbfs = value; }
        }

        /// <summary>
        /// The drive is accessible
        /// </summary>
        public bool IsReady
        {
            get { return this.info.IsReady; }
        }

        /// <summary>
        /// The file system supports sparse file
        /// </summary>
        public bool IsSparse
        {
            get { return this.isSparse; }
        }

        /// <summary>
        /// The size of the drive
        /// </summary>
        public long Size
        {
            get { return this.info.TotalSize; }
        }

        /// <summary>
        /// The ammount of free user space
        /// </summary>
        public long Free
        {
            get { return this.info.AvailableFreeSpace; }
        }

        /// <summary>
        /// The ammount of used user space
        /// </summary>
        public long Used
        {
            get { return this.Size - this.Free; }
        }

        // Methods

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="info">DriveInfo</param>
        internal OSDrive(DriveInfo info)
        {
            this.info = info;

            FSFeature volFeatures;
            StringBuilder volName = new StringBuilder(261);
            StringBuilder volFs = new StringBuilder(261);

            uint volSn;
            uint volMaxFile;

            Native.GetVolumeInformation(info.Name, volName, 261, 
                out volSn, out volMaxFile, out volFeatures, volFs, 261);

            isSparse = volFeatures.HasFlag(FSFeature.SupportsSparseFiles);
        }

        /// <summary>
        /// Updates the drive
        /// </summary>
        public void Update()
        {
        }

        /// <summary>
        /// Closes the drive
        /// </summary>
        public void Close()
        {
        }

        /// <summary>
        /// Enumerates files in a directory of the drive
        /// </summary>
        /// <param name="path">The full path</param>
        /// <returns>The filenames</returns>
        /// <exception cref="System.ArgumentException">The path is invalid or the root mismath</exception>
        /// <exception cref="System.Exception">On operation failure</exception>
        public String[] GetFilenames(String path)
        {
            path = System.IO.Path.GetFullPath(path);
            if(Char.ToUpper(path[0]) != Char.ToUpper(this.Name[0]))
                throw new ArgumentException("The path does not belong to the drive");

            System.IO.DirectoryInfo di = new System.IO.DirectoryInfo(path);
            var names = from fi in di.GetFiles() select fi.Name;

            return names.ToArray();
        }
    }
}
